package com.lonely.inventory.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.core.page.Condition;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.enums.DataScope;
import com.lonely.common.exception.BusinessException;
import com.lonely.common.threadlocals.DataPermissionThreadLocal;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.goods.service.IGoodsService;
import com.lonely.inventory.domain.dto.stockup.*;
import com.lonely.inventory.domain.entity.SysInventoryStorageArchive;
import com.lonely.inventory.domain.entity.SysStockUpInventory;
import com.lonely.inventory.domain.entity.SysStockUpInventorySizeInfo;
import com.lonely.inventory.domain.vo.stockup.*;
import com.lonely.inventory.enums.StockUpInventoryEnum;
import com.lonely.inventory.enums.StorageArchiveEnum;
import com.lonely.inventory.mapper.SysStockUpInventoryMapper;
import com.lonely.inventory.service.*;
import com.lonely.order.domain.dto.api.NumberInfo;
import com.lonely.order.domain.dto.order.SkcStickerQrCodeDTO;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/9/24 15:09
 * @description: 备货库存服务实现类
 */
@Service
public class StockUpInventoryServiceImpl extends ServiceImpl<SysStockUpInventoryMapper, SysStockUpInventory> implements IStockUpInventoryService {

    @Autowired
    private IStockUpInventorySizeInfoService stockUpInventorySizeInfoService;

    @Autowired
    private IStorageArchiveService storageArchiveService;

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IStockUpInventoryLogService stockUpInventoryLogService;

    @Autowired
    private IStockUpInventoryFlowWaterService stockUpInventoryFlowWaterService;

    @Autowired
    private IOrderService orderService;

    /**
     * 分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<StockUpInventoryPageQueryVo> page(StockUpInventoryPageQueryDto queryDto) {
        DataPermissionThreadLocal.setDataPermission(DataScope.ORDER_FACTORY, "o.factory_permission");
        Page<StockUpInventoryPageQueryVo> page = Condition.page(queryDto);
        page = super.getBaseMapper().page(page, queryDto);

        if (CollUtil.isNotEmpty(page.getRecords())) {
            // 备货库存与尺码的映射信息
            List<Long> stockUpInventoryIds = page.getRecords().stream().map(StockUpInventoryPageQueryVo::getId).collect(Collectors.toList());
            List<SysStockUpInventorySizeInfo> stockUpInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                    .in(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventoryIds)
                    .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
            );
            Map<Long, List<SysStockUpInventorySizeInfo>> stockUpInventorySizeMap = stockUpInventorySizeInfos.stream().collect(Collectors.groupingBy(SysStockUpInventorySizeInfo::getStockUpInventoryId));

            // 获取库位档案映射
            List<Long> storageArchiveIds = stockUpInventorySizeInfos.stream().map(SysStockUpInventorySizeInfo::getStorageArchiveId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<Long, String> storageArchiveNameMap = new HashMap<>();
            if (CollUtil.isNotEmpty(storageArchiveIds)) {
                storageArchiveNameMap.putAll(this.storageArchiveService.listByIds(storageArchiveIds).stream().collect(Collectors.toMap(BaseEntity::getId, SysInventoryStorageArchive::getStorageName, (x, y) -> x)));
            }


            page.setRecords(page.getRecords().stream().peek(x -> {
                if (!stockUpInventorySizeMap.containsKey(x.getId())) {
                    return;
                }

                List<StockUpInventoryPageSizeInfoVo> sizeInfos = new ArrayList<>();
                Map<String, List<SysStockUpInventorySizeInfo>> sizeNameMap = stockUpInventorySizeInfos.stream()
                        .filter(currentSizeInfo -> Objects.equals(currentSizeInfo.getStockUpInventoryId(), x.getId()))
                        .collect(Collectors.groupingBy(currentSizeInfo -> String.format("%s_%s", currentSizeInfo.getSizeName(), currentSizeInfo.getColor())));
                for (Map.Entry<String, List<SysStockUpInventorySizeInfo>> entry : sizeNameMap.entrySet()) {
                    StockUpInventoryPageSizeInfoVo pageSizeInfoVo = new StockUpInventoryPageSizeInfoVo();

                    String[] split = entry.getKey().split("_");
                    pageSizeInfoVo.setSizeName(split[0]);
                    pageSizeInfoVo.setColor(split[1]);
                    int totalQuantity = Optional.ofNullable(entry.getValue()).orElse(new ArrayList<>())
                            .stream().mapToInt(currentSize -> ObjectUtil.defaultIfNull(currentSize.getStockQuantity(), 0))
                            .sum();
                    pageSizeInfoVo.setStockQuantity(totalQuantity);
                    sizeInfos.add(pageSizeInfoVo);
                }
                x.setSizeInfos(sizeInfos);


                // 设置SKC库位总览
                String storageLocation = stockUpInventorySizeMap.get(x.getId()).stream().map(currentSize -> {
                    if (currentSize.getStorageArchiveId() == null) {
                        return null;
                    }
                    if (!storageArchiveNameMap.containsKey(currentSize.getStorageArchiveId())) {
                        return null;
                    }
                    return storageArchiveNameMap.get(currentSize.getStorageArchiveId());
                }).filter(Objects::nonNull).distinct().collect(Collectors.joining("、"));
                x.setStorageLocation(storageLocation);
            }).collect(Collectors.toList()));
        }
        return page;
    }

    /**
     * 新增备货库存时，根据条件查询商品列表
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<QueryAddStockUpInventoryPageVO> addStockUpInventoryPage(QueryAddStockUpInventoryPageDTO queryDto) {
        DataPermissionThreadLocal.setDataPermission(DataScope.ORDER_FACTORY, "o.factory_permission");
        Page<QueryAddStockUpInventoryPageVO> page = Condition.page(queryDto);
        Page<QueryAddStockUpInventoryPageTempResultDTO> addStockUpInventoryPageTempResultDTOPage = super.getBaseMapper().addStockUpInventoryPage(page, queryDto);

        Page<QueryAddStockUpInventoryPageVO> resultPage = new Page<>();
        if (CollUtil.isEmpty(addStockUpInventoryPageTempResultDTOPage.getRecords())) {
            return resultPage;
        }

        // 处理颜色和尺码
        List<String> skuList = addStockUpInventoryPageTempResultDTOPage.getRecords().stream().map(QueryAddStockUpInventoryPageTempResultDTO::getSku).distinct().collect(Collectors.toList());
        Map<String, Map<String, List<String>>> skcSizeNamesAndColorsMap = this.extractOrderSizeNamesAndColors(skuList);
        resultPage.setRecords(addStockUpInventoryPageTempResultDTOPage.getRecords().stream().map(x -> {
            QueryAddStockUpInventoryPageVO queryAddStockUpInventoryPageVO = new QueryAddStockUpInventoryPageVO();
            queryAddStockUpInventoryPageVO.setPic(x.getPic());
            queryAddStockUpInventoryPageVO.setDesignCode(x.getDesignCode());
            queryAddStockUpInventoryPageVO.setSkc(x.getSku());

            if (skcSizeNamesAndColorsMap.containsKey(x.getSku())) {
                Map<String, List<String>> sizeNamesAndColorsMap = skcSizeNamesAndColorsMap.get(x.getSku());
                if (sizeNamesAndColorsMap.containsKey("colors")) {
                    queryAddStockUpInventoryPageVO.setColors(String.join(",", sizeNamesAndColorsMap.get("colors")));
                }
                if (sizeNamesAndColorsMap.containsKey("sizeNames")) {
                    queryAddStockUpInventoryPageVO.setSize(String.join(",", sizeNamesAndColorsMap.get("sizeNames")));
                }
            }
            return queryAddStockUpInventoryPageVO;
        }).collect(Collectors.toList()));

        return resultPage;
    }

    /**
     * 提取skc集合对应的尺码和颜色
     *
     * @param skcList
     * @return
     */
    private Map<String, Map<String, List<String>>> extractOrderSizeNamesAndColors(List<String> skcList) {
        if (CollUtil.isEmpty(skcList)) {
            return new HashMap<>();
        }

        List<SysOrder> sysOrders = this.orderService.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getSku, skcList)
        );
        Map<String, List<SysOrder>> skuOrdersMap = sysOrders.stream().collect(Collectors.groupingBy(SysOrder::getSku));

        Map<String, Map<String, List<String>>> resultMap = new HashMap<>();
        for (Map.Entry<String, List<SysOrder>> entry : skuOrdersMap.entrySet()) {
            if (CollUtil.isEmpty(entry.getValue())) {
                resultMap.put(entry.getKey(), new HashMap<>());
                continue;
            }

            Map<String, List<String>> sizeAndColorsMap = new HashMap<>();
            List<String> colors = entry.getValue().stream().map(SysOrder::getColor).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
            sizeAndColorsMap.put("colors", colors);

            String orderInfo = entry.getValue().stream().map(SysOrder::getOrderInfo).filter(StrUtil::isNotBlank).findFirst().orElse(null);
            if (StrUtil.isNotBlank(orderInfo)) {
                List<NumberInfo> orderInfoNumbers = JSON.parseArray(orderInfo, NumberInfo.class);
                if (CollUtil.isNotEmpty(orderInfoNumbers)) {
                    List<String> sizeNames = orderInfoNumbers.stream().map(NumberInfo::getSizeName).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
                    sizeAndColorsMap.put("sizeNames", sizeNames);
                }
            }

            resultMap.put(entry.getKey(), sizeAndColorsMap);
        }
        return resultMap;
    }


    /**
     * 新增备货库存
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addStockUpInventory(AddStockUpInventoryDTO submitDto) {
        Map<String, Map<String, List<String>>> skcSizeNamesAndColorsMap = this.extractOrderSizeNamesAndColors(Lists.newArrayList(submitDto.getSkc()));
        if (skcSizeNamesAndColorsMap.isEmpty()) {
            throw new BusinessException("SKC对应数据不存在");
        }

        // 获取尺码和颜色信息
        Map<String, List<String>> sizeAndColorsMap = skcSizeNamesAndColorsMap.get(submitDto.getSkc());
        List<String> sizeNames = sizeAndColorsMap.get("sizeNames");
        List<String> colors = sizeAndColorsMap.get("colors");

        if (CollUtil.isEmpty(sizeNames) || CollUtil.isEmpty(colors)) {
            throw new BusinessException("商品尺码和颜色不能为空");
        }

        // 构建备货库存信息
        SysStockUpInventory stockUpInventory = new SysStockUpInventory();
        stockUpInventory.setSkc(submitDto.getSkc());
        stockUpInventory.setCreateBy(SecurityUtils.getUserId());
        stockUpInventory.setUpdateBy(SecurityUtils.getUserId());
        super.save(stockUpInventory);

        // 构建备货库存尺码明细信息
        List<SysStockUpInventorySizeInfo> sysStockUpInventorySizeInfos = new ArrayList<>();
        for (String sizeName : sizeNames) {
            for (String color : colors) {
                SysStockUpInventorySizeInfo sysStockUpInventorySizeInfo = new SysStockUpInventorySizeInfo();
                sysStockUpInventorySizeInfo.setStockUpInventoryId(stockUpInventory.getId());
                sysStockUpInventorySizeInfo.setSizeName(sizeName);
                sysStockUpInventorySizeInfo.setStockQuantity(0);
                sysStockUpInventorySizeInfo.setStorageArchiveId(null);
                sysStockUpInventorySizeInfo.setColor(color);
                sysStockUpInventorySizeInfo.setCreateBy(SecurityUtils.getUserId());
                sysStockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
                sysStockUpInventorySizeInfos.add(sysStockUpInventorySizeInfo);
            }
        }
        this.stockUpInventorySizeInfoService.saveBatch(sysStockUpInventorySizeInfos);

        // 添加日志
        this.stockUpInventoryLogService.addStockUpInventoryLog(stockUpInventory, sysStockUpInventorySizeInfos);

        // 添加流水
        this.stockUpInventoryFlowWaterService.addFlowWater(stockUpInventory, StockUpInventoryEnum.StockUpInventoryOperationType.ADD, null, sysStockUpInventorySizeInfos);
    }

    /**
     * 根据备货库存id查询尺码明细信息
     *
     * @param stockUpInventoryId
     * @return
     */
    @Override
    public List<StockUpInventorySizeInfoVo> getStockUpInventorySizeInfoList(Long stockUpInventoryId) {
        List<SysStockUpInventorySizeInfo> stockUpInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventoryId)
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code));

        if (CollUtil.isEmpty(stockUpInventorySizeInfos)) {
            return new ArrayList<>();
        }

        // 获取库位id和库位名称的映射信息
        List<Long> storageArchiveIds = stockUpInventorySizeInfos.stream().map(SysStockUpInventorySizeInfo::getStorageArchiveId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<Long, String> archiveNameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(storageArchiveIds)) {
            archiveNameMap.putAll(this.storageArchiveService.listByIds(storageArchiveIds).stream().collect(Collectors.toMap(BaseEntity::getId, SysInventoryStorageArchive::getStorageName, (x, y) -> x)));
        }
        List<StockUpInventorySizeInfoVo> sizeInfos = new ArrayList<>();
        Map<String, List<SysStockUpInventorySizeInfo>> sizeNameMap = stockUpInventorySizeInfos.stream().collect(Collectors.groupingBy(x -> String.format("%s_%s", x.getSizeName(), x.getColor())));
        for (Map.Entry<String, List<SysStockUpInventorySizeInfo>> entry : sizeNameMap.entrySet()) {
            StockUpInventorySizeInfoVo stockUpInventorySizeInfoVo = new StockUpInventorySizeInfoVo();
            String[] split = entry.getKey().split("_");
            stockUpInventorySizeInfoVo.setSizeName(split[0]);
            stockUpInventorySizeInfoVo.setColor(split[1]);

            List<StockUpInventorySizeInventoryVo> sizeInventoryVos = new ArrayList<>();
            for (SysStockUpInventorySizeInfo sysStockUpInventorySizeInfo : entry.getValue()) {
                StockUpInventorySizeInventoryVo sizeQuantityVo = new StockUpInventorySizeInventoryVo();
                sizeQuantityVo.setStockUpInventoryId(sysStockUpInventorySizeInfo.getStockUpInventoryId());
                sizeQuantityVo.setStockUpInventorySizeInfoId(sysStockUpInventorySizeInfo.getId());
                sizeQuantityVo.setStockQuantity(sysStockUpInventorySizeInfo.getStockQuantity());
                sizeQuantityVo.setStorageArchiveId(sysStockUpInventorySizeInfo.getStorageArchiveId());
                if (archiveNameMap.containsKey(sysStockUpInventorySizeInfo.getStorageArchiveId())) {
                    sizeQuantityVo.setStorageName(archiveNameMap.get(sysStockUpInventorySizeInfo.getStorageArchiveId()));
                }
                sizeInventoryVos.add(sizeQuantityVo);
            }
            stockUpInventorySizeInfoVo.setSizeInventorys(sizeInventoryVos);
            sizeInfos.add(stockUpInventorySizeInfoVo);
        }
        return sizeInfos;


//        return stockUpInventorySizeInfos.stream().map(currentSize -> {
//            StockUpInventorySizeInfoVo stockUpInventorySizeInfoVo = new StockUpInventorySizeInfoVo();
//            stockUpInventorySizeInfoVo.setStockUpInventoryId(currentSize.getStockUpInventoryId());
//            stockUpInventorySizeInfoVo.setStockUpInventorySizeInfoId(currentSize.getId());
//            stockUpInventorySizeInfoVo.setColor(currentSize.getColor());
//            stockUpInventorySizeInfoVo.setSizeName(currentSize.getSizeName());
//            stockUpInventorySizeInfoVo.setStockQuantity(currentSize.getStockQuantity());
//            stockUpInventorySizeInfoVo.setStorageArchiveId(currentSize.getStorageArchiveId());
//            if (archiveNameMap.containsKey(currentSize.getStorageArchiveId())) {
//                stockUpInventorySizeInfoVo.setStorageName(archiveNameMap.get(currentSize.getStorageArchiveId()));
//            }
//            return stockUpInventorySizeInfoVo;
//        }).collect(Collectors.toList());
    }


    /**
     * 入库
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void putStorage(SubmitStockUpInventorySizeDTO submitDto) {
        SysStockUpInventory stockUpInventory = super.getById(submitDto.getStockUpInventoryId());
        Assert.notNull(stockUpInventory, "备货库存不存在");

        List<StockUpInventorySizeInventoryVo> submitSizeInfos = submitDto.getSizeInfos().stream().filter(x -> CollUtil.isNotEmpty(x.getSizeInventorys()))
                .flatMap(x -> x.getSizeInventorys().stream())
                .filter(x -> x.getOperationNumber() != null)
                .filter(x -> x.getOperationNumber() > 0)
                .filter(x -> x.getStorageArchiveId() != null)
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(submitSizeInfos)) {
            throw new BusinessException("没有待入库的尺码");
        }

        // 更新备货库存最近出入库时间
        stockUpInventory.setLastPutOutStorageTime(new Date());
        stockUpInventory.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(stockUpInventory);

        // 修改前的数据
        List<SysStockUpInventorySizeInfo> oldInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
        );


        // 更新尺码信息
        Map<Long, StockUpInventorySizeInventoryVo> submitSizeInfoMap = submitSizeInfos.stream()
                .collect(Collectors.toMap(StockUpInventorySizeInventoryVo::getStockUpInventorySizeInfoId, Function.identity(), (x, y) -> x));
        Set<Long> submitSizeInfoIds = submitSizeInfoMap.keySet();
        List<SysStockUpInventorySizeInfo> stockUpInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, submitDto.getStockUpInventoryId())
                .in(SysStockUpInventorySizeInfo::getId, submitSizeInfoIds));
        for (SysStockUpInventorySizeInfo stockUpInventorySizeInfo : stockUpInventorySizeInfos) {
            StockUpInventorySizeInventoryVo submitSizeInfo = submitSizeInfoMap.get(stockUpInventorySizeInfo.getId());
            stockUpInventorySizeInfo.setStorageArchiveId(submitSizeInfo.getStorageArchiveId());
            stockUpInventorySizeInfo.setStockQuantity(ObjectUtil.defaultIfNull(stockUpInventorySizeInfo.getStockQuantity(), 0) + submitSizeInfo.getOperationNumber());
            stockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
        }
        this.stockUpInventorySizeInfoService.updateBatchById(stockUpInventorySizeInfos);

        // 修改后的数据
        List<SysStockUpInventorySizeInfo> newInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
        );

        // 添加操作日志
        this.stockUpInventoryLogService.putStockUpInventoryLog(stockUpInventory, oldInventorySizeInfos, newInventorySizeInfos);

        // 添加流水数据
        this.stockUpInventoryFlowWaterService.addFlowWater(stockUpInventory, StockUpInventoryEnum.StockUpInventoryOperationType.PUT_STORAGE, oldInventorySizeInfos, newInventorySizeInfos);
    }

    /**
     * 出库
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void outStorage(SubmitStockUpInventorySizeDTO submitDto) {
        SysStockUpInventory stockUpInventory = super.getById(submitDto.getStockUpInventoryId());
        Assert.notNull(stockUpInventory, "备货库存不存在");

        List<StockUpInventorySizeInventoryVo> submitSizeInfos = submitDto.getSizeInfos().stream().filter(x -> CollUtil.isNotEmpty(x.getSizeInventorys()))
                .flatMap(x -> x.getSizeInventorys().stream())
                .filter(x -> x.getOperationNumber() != null)
                .filter(x -> x.getOperationNumber() > 0)
                .filter(x -> x.getStorageArchiveId() != null)
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(submitSizeInfos)) {
            throw new BusinessException("没有待出库的尺码");
        }

        // 更新备货库存最近出入库时间
        stockUpInventory.setLastPutOutStorageTime(new Date());
        stockUpInventory.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(stockUpInventory);

        // 修改前的数据
        List<SysStockUpInventorySizeInfo> oldInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
        );

        // 更新尺码信息
        Map<Long, StockUpInventorySizeInventoryVo> submitSizeInfoMap = submitSizeInfos.stream().collect(Collectors.toMap(StockUpInventorySizeInventoryVo::getStockUpInventorySizeInfoId, Function.identity(), (x, y) -> x));
        Set<Long> submitSizeInfoIds = submitSizeInfoMap.keySet();
        List<SysStockUpInventorySizeInfo> stockUpInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, submitDto.getStockUpInventoryId())
                .in(SysStockUpInventorySizeInfo::getId, submitSizeInfoIds));
        for (SysStockUpInventorySizeInfo stockUpInventorySizeInfo : stockUpInventorySizeInfos) {
            StockUpInventorySizeInventoryVo submitSizeInfo = submitSizeInfoMap.get(stockUpInventorySizeInfo.getId());
            stockUpInventorySizeInfo.setStorageArchiveId(submitSizeInfo.getStorageArchiveId());
            stockUpInventorySizeInfo.setStockQuantity(ObjectUtil.defaultIfNull(stockUpInventorySizeInfo.getStockQuantity(), 0) - submitSizeInfo.getOperationNumber());
            if (stockUpInventorySizeInfo.getStockQuantity() < 0) {
                stockUpInventorySizeInfo.setStockQuantity(0);
            }
            stockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
        }
        this.stockUpInventorySizeInfoService.updateBatchById(stockUpInventorySizeInfos);

        // 修改后的数据
        List<SysStockUpInventorySizeInfo> newInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
        );

        // 添加操作日志
        this.stockUpInventoryLogService.outStockUpInventoryLog(stockUpInventory, oldInventorySizeInfos, newInventorySizeInfos);

        // 添加流水数据
        this.stockUpInventoryFlowWaterService.addFlowWater(stockUpInventory, StockUpInventoryEnum.StockUpInventoryOperationType.OUT_STORAGE, oldInventorySizeInfos, newInventorySizeInfos);
    }

    /**
     * 调拨
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(TransferStockUpInventorySizeDTO submitDto) {
        SysStockUpInventory stockUpInventory = super.getById(submitDto.getStockUpInventoryId());
        Assert.notNull(stockUpInventory, "备货库存不存在");

        List<StockUpInventorySizeInventoryVo> submitSizeInfos = submitDto.getSizeInfos().stream().filter(x -> CollUtil.isNotEmpty(x.getSizeInventorys()))
                .flatMap(x -> x.getSizeInventorys().stream())
                .filter(x -> x.getOperationNumber() != null)
                .filter(x -> x.getOperationNumber() > 0)
                .filter(x -> x.getStorageArchiveId() != null)
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(submitSizeInfos)) {
            throw new BusinessException("没有待调拨的尺码");
        }

        // 更新备货库存最近出入库时间
        stockUpInventory.setLastPutOutStorageTime(new Date());
        stockUpInventory.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(stockUpInventory);

        // 修改前的数据
        List<SysStockUpInventorySizeInfo> oldInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
                .orderByAsc(SysStockUpInventorySizeInfo::getSizeName, SysStockUpInventorySizeInfo::getColor)
        );

        // 更新尺码信息
        List<SysStockUpInventorySizeInfo> transferStockUpInventorySizeInfos = new ArrayList<>();
        for (StockUpInventorySizeInventoryVo submitSizeInfo : submitSizeInfos) {
            // 更新当前库存尺码信息
            SysStockUpInventorySizeInfo currentStockUpInventorySizeInfo = this.stockUpInventorySizeInfoService.getById(submitSizeInfo.getStockUpInventorySizeInfoId());
            if (currentStockUpInventorySizeInfo.getStorageArchiveId() == null) {
                throw new BusinessException(String.format("尺码：%s-%s 调拨前没有设置库位，无法进行调拨", currentStockUpInventorySizeInfo.getSizeName(), currentStockUpInventorySizeInfo.getColor()));
            }

            // 判断当前库位和调拨库位是否是同一个
            if (Objects.equals(currentStockUpInventorySizeInfo.getStorageArchiveId(), submitDto.getTransferTargetStorageArchiveId())) {
                // 同一个仓库，不存在调拨，跳过
                continue;
            }

            // 原库位执行出库
            // 获取调拨数量
            int currentStockQuantity = ObjectUtil.defaultIfNull(currentStockUpInventorySizeInfo.getStockQuantity(), 0);
            int transferNumber = currentStockQuantity > submitSizeInfo.getOperationNumber() ? submitSizeInfo.getOperationNumber() : currentStockQuantity;
            currentStockUpInventorySizeInfo.setStockQuantity(currentStockQuantity - transferNumber);
            currentStockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
            this.stockUpInventorySizeInfoService.updateById(currentStockUpInventorySizeInfo);

            // 调拨库位执行入库
            SysStockUpInventorySizeInfo targetStockUpInventorySizeInfo = this.stockUpInventorySizeInfoService.getOne(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                    .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, submitDto.getStockUpInventoryId())
                    .eq(SysStockUpInventorySizeInfo::getSizeName, currentStockUpInventorySizeInfo.getSizeName())
                    .eq(SysStockUpInventorySizeInfo::getColor, currentStockUpInventorySizeInfo.getColor())
                    .eq(SysStockUpInventorySizeInfo::getStorageArchiveId, submitDto.getTransferTargetStorageArchiveId())
            );
            if (targetStockUpInventorySizeInfo == null) {
                // 目标库位对应的备货库存尺码信息不存在，则创建在入库
                targetStockUpInventorySizeInfo = new SysStockUpInventorySizeInfo();
                targetStockUpInventorySizeInfo.setStockUpInventoryId(submitDto.getStockUpInventoryId());
                targetStockUpInventorySizeInfo.setSizeName(currentStockUpInventorySizeInfo.getSizeName());
                targetStockUpInventorySizeInfo.setStockQuantity(transferNumber);
                targetStockUpInventorySizeInfo.setStorageArchiveId(submitDto.getTransferTargetStorageArchiveId());
                targetStockUpInventorySizeInfo.setColor(currentStockUpInventorySizeInfo.getColor());
                targetStockUpInventorySizeInfo.setCreateBy(SecurityUtils.getUserId());
                targetStockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
                this.stockUpInventorySizeInfoService.save(targetStockUpInventorySizeInfo);
            } else {
                // 更新库存数量
                targetStockUpInventorySizeInfo.setStockQuantity(ObjectUtil.defaultIfNull(targetStockUpInventorySizeInfo.getStockQuantity(), 0) + transferNumber);
                targetStockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
                this.stockUpInventorySizeInfoService.updateById(targetStockUpInventorySizeInfo);
            }
            transferStockUpInventorySizeInfos.add(targetStockUpInventorySizeInfo);
        }

        if (CollUtil.isEmpty(transferStockUpInventorySizeInfos)) {
            throw new BusinessException("调拨前后库位一致,不进行处理...");
        }

        // 修改后的数据
        List<SysStockUpInventorySizeInfo> newInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
                .orderByAsc(SysStockUpInventorySizeInfo::getSizeName, SysStockUpInventorySizeInfo::getColor)
        );

        // 添加操作日志
        this.stockUpInventoryLogService.transferStockUpInventoryLog(stockUpInventory, oldInventorySizeInfos, newInventorySizeInfos);

        // 添加流水数据
        this.stockUpInventoryFlowWaterService.addFlowWater(stockUpInventory, StockUpInventoryEnum.StockUpInventoryOperationType.TRANSFER_STORAGE, oldInventorySizeInfos, newInventorySizeInfos);
    }

    /**
     * 备货上架
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void stockUpStockPutAway(StockUpStockPutAwayDTO submitDto) {
        SysInventoryStorageArchive storageArchive = this.storageArchiveService.getByStorageCode(submitDto.getStorageCode());
        Assert.notNull(storageArchive, "没有查询到库位信息..");
        Assert.isTrue(Objects.equals(storageArchive.getStorageType(), StorageArchiveEnum.StorageTypeEnum.STOCK_UP_STORAGE.getStorageTypeCode()), "该库位类型不是备货库存");

        // 将相同订单号合并
        Map<String, List<SkcStickerQrCodeDTO>> orderMap = submitDto.getSkcStickerCodes().stream().collect(Collectors.groupingBy(SkcStickerQrCodeDTO::getProduceOrderId));
        List<String> produceOrderIds = new ArrayList<>(orderMap.keySet());
        Map<Long, SysOrder> produceOrderMap = this.orderService.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, produceOrderIds)
        ).stream().collect(Collectors.toMap(SysOrder::getProduceOrderId, Function.identity(), (x, y) -> x));


        for (Map.Entry<String, List<SkcStickerQrCodeDTO>> currentEntry : orderMap.entrySet()) {
            // 将相同尺码进行合并
            Map<String, Long> sizeCountMap = currentEntry.getValue().stream().collect(Collectors.groupingBy(SkcStickerQrCodeDTO::getSizeName, Collectors.counting()));
            SysOrder sysOrder = produceOrderMap.get(Long.valueOf(currentEntry.getKey()));
            Assert.notNull(sysOrder, String.format("没有查询到订单号：%s 的信息..", currentEntry.getKey()));

            // 判断是否存在该skc对应的备货库存信息
            SysStockUpInventory stockUpInventory = super.getOne(new LambdaQueryWrapper<SysStockUpInventory>()
                    .eq(SysStockUpInventory::getSkc, sysOrder.getSku())
                    .eq(SysStockUpInventory::getStatus, CommonStatus.ENABLE.code)
            );
            boolean existsOldStockUpInventory = stockUpInventory != null;
            if (stockUpInventory == null) {
                // 还没有该skc对应的备货库存信息,新建备货库存信息
                stockUpInventory = new SysStockUpInventory();
                stockUpInventory.setSkc(sysOrder.getSku());
                stockUpInventory.setLastPutOutStorageTime(new Date());
                stockUpInventory.setCreateBy(SecurityUtils.getUserId());
                stockUpInventory.setUpdateBy(SecurityUtils.getUserId());
                super.save(stockUpInventory);
            }

            // 修改前的数据
            List<SysStockUpInventorySizeInfo> oldInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                    .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                    .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
                    .orderByAsc(SysStockUpInventorySizeInfo::getSizeName, SysStockUpInventorySizeInfo::getColor)
            );

            // 处理尺码明细
            for (Map.Entry<String, Long> sizeQuantityEntry : sizeCountMap.entrySet()) {
                if (existsOldStockUpInventory) {
                    // 判断是否存在该尺码的库存数据
                    // 判断该尺码是否已存在
                    SysStockUpInventorySizeInfo oldStockUpInventorySizeInfo = this.stockUpInventorySizeInfoService.getOne(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                            .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                            .eq(SysStockUpInventorySizeInfo::getSizeName, sizeQuantityEntry.getKey())
                            .eq(SysStockUpInventorySizeInfo::getColor, sysOrder.getColor())
                            .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
                    );
                    if (oldStockUpInventorySizeInfo != null) {
                        oldStockUpInventorySizeInfo.setStockQuantity(oldStockUpInventorySizeInfo.getStockQuantity() + MapUtil.getInt(sizeCountMap, sizeQuantityEntry.getKey(), 0));
                        oldStockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
                    }
                    this.stockUpInventorySizeInfoService.updateById(oldStockUpInventorySizeInfo);
                    continue;
                }

                // 不存在该尺码的明细，新建该尺码的明细数据
                SysStockUpInventorySizeInfo stockUpInventorySizeInfo = new SysStockUpInventorySizeInfo();
                stockUpInventorySizeInfo.setStockUpInventoryId(stockUpInventory.getId());
                stockUpInventorySizeInfo.setSizeName(sizeQuantityEntry.getKey());
                stockUpInventorySizeInfo.setStockQuantity(MapUtil.getInt(sizeCountMap, sizeQuantityEntry.getKey(), 0));
                stockUpInventorySizeInfo.setStorageArchiveId(storageArchive.getId());
                stockUpInventorySizeInfo.setColor(sysOrder.getColor());
                stockUpInventorySizeInfo.setCreateBy(SecurityUtils.getUserId());
                stockUpInventorySizeInfo.setUpdateBy(SecurityUtils.getUserId());
                this.stockUpInventorySizeInfoService.save(stockUpInventorySizeInfo);
            }

            // 修改后的数据
            List<SysStockUpInventorySizeInfo> newInventorySizeInfos = this.stockUpInventorySizeInfoService.list(new LambdaQueryWrapper<SysStockUpInventorySizeInfo>()
                    .eq(SysStockUpInventorySizeInfo::getStockUpInventoryId, stockUpInventory.getId())
                    .eq(SysStockUpInventorySizeInfo::getStatus, CommonStatus.ENABLE.code)
                    .orderByAsc(SysStockUpInventorySizeInfo::getSizeName, SysStockUpInventorySizeInfo::getColor)
            );

            // 添加操作日志
            this.stockUpInventoryLogService.putAwayStockUpInventoryLog(stockUpInventory, oldInventorySizeInfos, newInventorySizeInfos);

            // 添加流水数据
            this.stockUpInventoryFlowWaterService.addFlowWater(stockUpInventory, StockUpInventoryEnum.StockUpInventoryOperationType.STOCK_PUT_AWAY, oldInventorySizeInfos, newInventorySizeInfos);
        }

    }


}
